/*
 * @Date: 2022-03-07 21:45:52
 * @Version: 1.0.0
 * @Author: minichen
 * @Description: 多段线绘制
 * @FilePath: \bmap-libs\src\plugin\multiPolyline.js
 * @LastEditTime: 2022-03-16 21:35:26
 * @LastEditors: minichen
 */
import { debounce } from 'throttle-debounce';
import customOverlay from './customOverlay';

export default function () {
  const BMapGLLib = (window.BMapGLLib = window.BMapGLLib || {});

  let BMap = window.BMap || window.BMapGL;

  if (!BMap) {
    console.error('bamp-libs: BMap or BMapGL is not found!');
    return;
  }

  const CustomOverlay = customOverlay(BMap);

  function MultiPolyline(points, options) {
    const _options = {
      zIndex: 1,
      strokeColor: '#00f',
      strokeWeight: 2,
      strokeOpacity: 1,
      delay: 100,
      pane: 'markerPane',
    };

    // 参数
    this._points = points;
    this._options = { ..._options, ...options };

    // 状态
    this._initialized = false; // 是否初始化
    this._removed = false; // 是否移除
    this._needUpdate = false; // 是否需要更新

    // 属性
    this._map = null; // 地图实例
    this._container = null; // dom节点
    this._size = null; // dom尺寸
    this._ctx = null; // canvas绘制上下文
    this._draw = this._options.delay > 0 ? debounce(this._options.delay, false, draw) : draw.bind(this); // 绘制方法

    // 增强子类
    CustomOverlay.call(this);
  }

  MultiPolyline.prototype = Object.create(CustomOverlay.prototype);
  MultiPolyline.prototype.constructor = MultiPolyline;

  MultiPolyline.prototype.initialize = function (map) {
    // 参数有误
    if (this._initialized === undefined) return;

    // 创建canvas
    const cvs = document.createElement('canvas');
    cvs.style.position = 'absolute';

    this._map = map;
    this._container = cvs;
    this._ctx = cvs.getContext('2d');

    // 设置层级
    this.setZIndex(this._options.zIndex);
    // 添加事件
    this._patchEventHandle(this._bindEvent);
    // 监听clearoverlays事件
    this._addClearoverlaysEvent();

    // 将canvas添加到dom中
    this._addDom();
    // 获取元素尺寸
    this._getContainerSize();

    this._initialized = true;

    return cvs;
  };

  MultiPolyline.prototype.draw = function () {
    if (!this._initialized) return;

    // 移除后重新添加节点
    if (this._removed) {
      // 重新添加节点
      this._addDom();
      // 重新绑定事件
      this._patchEventHandle(this._bindEvent);
      // 重新监听clearoverlays事件
      this._addClearoverlaysEvent();

      this._removed = false;
    }

    this._ctx.clearRect(0, 0, this._container.width, this._container.height);
    this._draw();
  };

  MultiPolyline.prototype.remove = function () {
    if (!this._initialized || this._removed) return;

    // 移除clearoverlays事件
    this._removeClearoverlaysEvent();
    // 移除节点事件
    this._patchEventHandle(this._unbindEvent);
    // 移除节点
    this._removeDom();

    this._removed = true;
  };

  function draw() {
    const bounds = this._map.getBounds();
    const size = this._map.getSize();

    // 过滤视区外的点
    const points = this._points.reduce((arr, _points) => {
      if (Array.isArray(_points) && _points.length > 1) {
        const len = _points.length;
        let sIdx = 0;
        let eIdx = 0;
        let exist = false;

        for (let i = 0; i < len; i++) {
          if (!exist && bounds.containsPoint(_points[i])) {
            sIdx = Math.max(i - 1, 0);
            exist = true;
          } else if (exist && !bounds.containsPoint(_points[i])) {
            eIdx = i;
            exist = false;
            arr.push(_points.slice(sIdx, eIdx + 1));
          }
        }
        if (exist && sIdx < len - 1) {
          arr.push(_points.slice(sIdx, len));
        }
      }
      return arr;
    }, []);

    // 设置尺寸、样式
    this._container.width = size.width;
    this._container.height = size.height;
    this._container.style.width = size.width + 'px';
    this._container.style.height = size.height + 'px';

    // 绘制
    this._ctx.strokeStyle = this._options.strokeColor;
    this._ctx.lineWidth = this._options.strokeWeight;
    this._ctx.globalAlpha = this._options.strokeOpacity;

    this._ctx.beginPath();
    points.forEach((_points) => {
      _points.forEach((_point, _i) => {
        const pixel = this._map.pointToOverlayPixel(_point);
        this._ctx[_i ? 'lineTo' : 'moveTo'](pixel.x, pixel.y);
      });
    });
    this._ctx.stroke();
  }

  BMapGLLib.MultiPolyline = MultiPolyline;
}
